use evm_interpreter::Opcode;

pub const G_ZERO: u64 = 0;
pub const G_BASE: u64 = 2;
pub const G_VERYLOW: u64 = 3;
pub const G_LOW: u64 = 5;
pub const G_MID: u64 = 8;
pub const G_HIGH: u64 = 10;
pub const G_JUMPDEST: u64 = 1;
pub const R_SUICIDE: i64 = 24000;
pub const G_CREATE: u64 = 32000;
pub const G_CALLVALUE: u64 = 9000;
pub const G_NEWACCOUNT: u64 = 25000;
pub const G_EXP: u64 = 10;
pub const G_MEMORY: u64 = 3;
pub const G_LOG: u64 = 375;
pub const G_LOGDATA: u64 = 8;
pub const G_LOGTOPIC: u64 = 375;
pub const G_SHA3: u64 = 30;
pub const G_SHA3WORD: u64 = 6;
pub const G_COPY: u64 = 3;
pub const G_BLOCKHASH: u64 = 20;
pub const G_CODEDEPOSIT: u64 = 200;

pub static STATIC_COST_TABLE: [Option<u64>; 256] = {
	let mut table = [None; 256];

	table[Opcode::STOP.as_usize()] = Some(G_ZERO);
	table[Opcode::CALLDATASIZE.as_usize()] = Some(G_BASE);
	table[Opcode::CODESIZE.as_usize()] = Some(G_BASE);
	table[Opcode::POP.as_usize()] = Some(G_BASE);
	table[Opcode::PC.as_usize()] = Some(G_BASE);
	table[Opcode::MSIZE.as_usize()] = Some(G_BASE);

	table[Opcode::ADDRESS.as_usize()] = Some(G_BASE);
	table[Opcode::ORIGIN.as_usize()] = Some(G_BASE);
	table[Opcode::CALLER.as_usize()] = Some(G_BASE);
	table[Opcode::CALLVALUE.as_usize()] = Some(G_BASE);
	table[Opcode::COINBASE.as_usize()] = Some(G_BASE);
	table[Opcode::TIMESTAMP.as_usize()] = Some(G_BASE);
	table[Opcode::NUMBER.as_usize()] = Some(G_BASE);
	table[Opcode::DIFFICULTY.as_usize()] = Some(G_BASE);
	table[Opcode::GASLIMIT.as_usize()] = Some(G_BASE);
	table[Opcode::GASPRICE.as_usize()] = Some(G_BASE);
	table[Opcode::GAS.as_usize()] = Some(G_BASE);

	table[Opcode::ADD.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SUB.as_usize()] = Some(G_VERYLOW);
	table[Opcode::NOT.as_usize()] = Some(G_VERYLOW);
	table[Opcode::LT.as_usize()] = Some(G_VERYLOW);
	table[Opcode::GT.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SLT.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SGT.as_usize()] = Some(G_VERYLOW);
	table[Opcode::EQ.as_usize()] = Some(G_VERYLOW);
	table[Opcode::ISZERO.as_usize()] = Some(G_VERYLOW);
	table[Opcode::AND.as_usize()] = Some(G_VERYLOW);
	table[Opcode::OR.as_usize()] = Some(G_VERYLOW);
	table[Opcode::XOR.as_usize()] = Some(G_VERYLOW);
	table[Opcode::BYTE.as_usize()] = Some(G_VERYLOW);
	table[Opcode::CALLDATALOAD.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH1.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH2.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH3.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH4.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH5.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH6.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH7.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH8.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH9.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH10.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH11.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH12.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH13.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH14.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH15.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH16.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH17.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH18.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH19.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH20.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH21.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH22.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH23.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH24.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH25.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH26.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH27.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH28.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH29.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH30.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH31.as_usize()] = Some(G_VERYLOW);
	table[Opcode::PUSH32.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP1.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP2.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP3.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP4.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP5.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP6.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP7.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP8.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP9.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP10.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP11.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP12.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP13.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP14.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP15.as_usize()] = Some(G_VERYLOW);
	table[Opcode::DUP16.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP1.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP2.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP3.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP4.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP5.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP6.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP7.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP8.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP9.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP10.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP11.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP12.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP13.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP14.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP15.as_usize()] = Some(G_VERYLOW);
	table[Opcode::SWAP16.as_usize()] = Some(G_VERYLOW);

	table[Opcode::MUL.as_usize()] = Some(G_LOW);
	table[Opcode::DIV.as_usize()] = Some(G_LOW);
	table[Opcode::SDIV.as_usize()] = Some(G_LOW);
	table[Opcode::MOD.as_usize()] = Some(G_LOW);
	table[Opcode::SMOD.as_usize()] = Some(G_LOW);
	table[Opcode::SIGNEXTEND.as_usize()] = Some(G_LOW);

	table[Opcode::ADDMOD.as_usize()] = Some(G_MID);
	table[Opcode::MULMOD.as_usize()] = Some(G_MID);
	table[Opcode::JUMP.as_usize()] = Some(G_MID);

	table[Opcode::JUMPI.as_usize()] = Some(G_HIGH);
	table[Opcode::JUMPDEST.as_usize()] = Some(G_JUMPDEST);

	table
};
